import os
import time
from tkinter import *
from tkinter import ttk, messagebox, filedialog
from urllib.parse import urlparse
from db_utils import TaskDB
from m3u8_parser import parse_m3u8, download_m3u8
from downloader import DownloadManager
import config

class M3U8DownloaderApp:
    def __init__(self, root):
        self.root = root
        self.root.title("M3U8视频下载工具")
        self.root.geometry("800x600")
        self.db = TaskDB(config.DB_NAME)
        self.create_widgets()
        self.load_tasks()
        self.download_manager = DownloadManager(self.db, max_workers=config.MAX_DOWNLOAD_THREADS)
        
        # 定期更新下载状态
        self.root.after(1000, self.update_download_status)
    
    def update_download_status(self):
        """定期更新下载状态"""
        self.download_manager.update_ui_status()
        self.root.after(1000, self.update_download_status)
    
    def create_widgets(self):
        # 创建选项卡
        notebook = ttk.Notebook(self.root)
        task_frame = ttk.Frame(notebook)
        download_frame = ttk.Frame(notebook)
        notebook.add(task_frame, text="创建任务")
        notebook.add(download_frame, text="任务下载")
        notebook.pack(fill=BOTH, expand=True)
        
        # 任务创建区域
        self.create_task_ui(task_frame)
        
        # 任务下载区域
        self.create_download_ui(download_frame)
    
    def update_ui(self, *args):
        """根据选择类型更新UI界面"""
        if self.source_type.get() == "file":
            self.browse_button.config(state="normal")
            self.url_entry.delete(0, END)
            self.url_entry.config(state="disabled")
        else:
            self.browse_button.config(state="normal")
            self.url_entry.config(state="normal")
    
    def browse_file(self):
        """打开文件选择对话框"""
        filename = filedialog.askopenfilename(
            title="选择M3U8文件",
            filetypes=[("M3U8文件", "*.m3u8"), ("所有文件", "*.*")]
        )
        if filename:
            self.url_entry.config(state="normal")
            self.url_entry.delete(0, END)
            self.url_entry.insert(0, filename)
            self.url_entry.config(state="disabled")
            
            # 自动提取文件名作为视频名称
            video_name = os.path.splitext(os.path.basename(filename))[0]
            self.name_entry.delete(0, END)
            self.name_entry.insert(0, video_name)
    
    def create_task_ui(self, parent):
        # URL输入区域
        ttk.Label(parent, text="M3U8来源:").grid(row=0, column=0, padx=5, pady=5)
        self.source_type = StringVar(value="url")
        ttk.Radiobutton(parent, text="URL", variable=self.source_type, value="url").grid(row=0, column=1)
        ttk.Radiobutton(parent, text="本地文件", variable=self.source_type, value="file").grid(row=0, column=2)
        
        self.url_entry = ttk.Entry(parent, width=50)
        self.url_entry.grid(row=1, column=0, columnspan=3, padx=5, pady=5, sticky=EW)
        
        self.browse_button = ttk.Button(parent, text="浏览...", command=self.browse_file)
        self.browse_button.grid(row=1, column=3, padx=5, pady=5)
        
        # 视频信息区域
        ttk.Label(parent, text="视频名称:").grid(row=2, column=0, padx=5, pady=5)
        self.name_entry = ttk.Entry(parent, width=50)
        self.name_entry.grid(row=2, column=1, columnspan=3, padx=5, pady=5, sticky=EW)
        
        ttk.Label(parent, text="Referer:").grid(row=3, column=0, padx=5, pady=5)
        self.refer_entry = ttk.Entry(parent, width=50)
        self.refer_entry.grid(row=3, column=1, columnspan=3, padx=5, pady=5, sticky=EW)
        
        ttk.Label(parent, text="保存路径:").grid(row=4, column=0, padx=5, pady=5)
        self.path_entry = ttk.Entry(parent, width=50)
        self.path_entry.grid(row=4, column=1, columnspan=2, padx=5, pady=5, sticky=EW)
        self.path_entry.insert(0, os.getcwd())
        
        ttk.Button(parent, text="选择路径", command=self.select_path).grid(row=4, column=3, padx=5, pady=5)
        
        # 创建任务按钮
        ttk.Button(parent, text="创建任务", command=self.create_task).grid(row=5, column=0, columnspan=4, pady=10)
        
        # 日志区域
        self.task_log = Text(parent, height=10, width=70)
        self.task_log.grid(row=6, column=0, columnspan=4, padx=5, pady=5)
        
        # 绑定事件
        self.source_type.trace_add("write", self.update_ui)
        self.update_ui()
    
    def create_download_ui(self, parent):
        # 任务列表
        columns = ("id", "name", "state", "progress")
        self.task_tree = ttk.Treeview(parent, columns=columns, show="headings")
        self.task_tree.heading("id", text="ID")
        self.task_tree.heading("name", text="视频名称")
        self.task_tree.heading("state", text="状态")
        self.task_tree.heading("progress", text="进度")
        self.task_tree.column("id", width=50)
        self.task_tree.column("name", width=200)
        self.task_tree.column("state", width=80)
        self.task_tree.column("progress", width=100)
        self.task_tree.pack(fill=BOTH, padx=5, pady=5, expand=True)
        
        # 控制按钮
        btn_frame = ttk.Frame(parent)
        btn_frame.pack(fill=X, padx=5, pady=5)
        
        ttk.Button(btn_frame, text="开始下载", command=self.start_download).pack(side=LEFT, padx=2)
        ttk.Button(btn_frame, text="暂停下载", command=self.pause_download).pack(side=LEFT, padx=2)
        ttk.Button(btn_frame, text="删除任务", command=self.delete_task).pack(side=LEFT, padx=2)
        ttk.Button(btn_frame, text="刷新列表", command=self.load_tasks).pack(side=RIGHT, padx=2)
        
        # 进度条
        self.progress_var = DoubleVar()
        self.progress_bar = ttk.Progressbar(
            parent, 
            variable=self.progress_var,
            maximum=100
        )
        self.progress_bar.pack(fill=X, padx=5, pady=5)
        
        # 下载日志
        self.download_log = Text(parent, height=10, width=70)
        self.download_log.pack(fill=BOTH, padx=5, pady=5, expand=True)
    
    def select_path(self):
        """选择保存路径"""
        path = filedialog.askdirectory()
        if path:
            self.path_entry.delete(0, END)
            self.path_entry.insert(0, path)
    
    def log_task(self, message):
        """记录任务创建日志"""
        self.task_log.insert(END, f"{time.strftime('%H:%M:%S')} - {message}\n")
        self.task_log.see(END)
    
    def log_download(self, message):
        """记录下载日志"""
        self.download_log.insert(END, f"{time.strftime('%H:%M:%S')} - {message}\n")
        self.download_log.see(END)
    
    def load_tasks(self):
        """从数据库加载任务列表"""
        # 清空树视图
        for item in self.task_tree.get_children():
            self.task_tree.delete(item)
        
        tasks = self.db.get_all_tasks()
        
        for task in tasks:
            task_id, name, state, total, downloaded = task['id'], task['name'], task['state'], task['totalNum'], task['downloaded']
            state_text = "已完成" if state == 1 else "待下载"
            progress = f"{downloaded}/{total}" if state != 1 else "100%"
            
            self.task_tree.insert("", END, values=(task_id, name, state_text, progress))
    
    def create_task(self):
        """创建下载任务并解析M3U8文件"""
        # 获取用户输入
        source = self.source_type.get()
        url_or_path = self.url_entry.get()
        name = self.name_entry.get()
        refer = self.refer_entry.get()
        save_path = self.path_entry.get()
        
        # 验证输入
        if not url_or_path:
            messagebox.showerror("错误", "请提供M3U8 URL或文件路径")
            return
            
        if not name:
            messagebox.showerror("错误", "请输入视频名称")
            return
        
        try:
            if source == "url":
                parsed_url = urlparse(url_or_path)
                base_url = f"{parsed_url.scheme}://{parsed_url.netloc}"
                if not refer:
                    refer = base_url
                content = download_m3u8(url_or_path, refer)
            else:
                with open(url_or_path, 'r', encoding='utf-8') as f:
                    content = f.read()
                if refer:
                    base_url = refer
                else:
                    base_url = os.path.dirname(url_or_path) or save_path
            
            # 解析M3U8内容
            key_url, segments = parse_m3u8(content, base_url, refer)
            
            # 生成唯一ID
            task_uid = str(self.db.generate_uid())
            
            # 保存到数据库
            task_id = self.db.create_m3u8_task(
                url=url_or_path,
                refer=refer,
                keyUrl=key_url,
                name=name,
                uid=task_uid,
                totalNum=len(segments),
                save_path=save_path
            )
            
            # 保存TS片段
            for order_num, (link, duration) in enumerate(segments):
                self.db.create_ts_segment(
                    order_num=order_num,
                    link=link,
                    second=duration,
                    m3u8Id=task_uid
                )
            
            self.log_task(f"任务创建成功: {name}\n共{len(segments)}个片段")
            
        except Exception as e:
            self.log_task(f"创建任务失败: {str(e)}")
            messagebox.showerror("错误", f"创建任务失败: {str(e)}")
    
    def get_selected_task_id(self):
        """获取选中的任务ID"""
        selected = self.task_tree.selection()
        if not selected:
            messagebox.showinfo("提示", "请先选择一个任务")
            return None
        return self.task_tree.item(selected[0], "values")[0]
    
    def start_download(self):
        """开始下载选中任务"""
        task_id = self.get_selected_task_id()
        if task_id is None:
            return
        
        save_path = self.path_entry.get()
        task_info = self.db.get_task(task_id)
        
        if task_info['state'] == 1:
            messagebox.showinfo("提示", "该任务已完成下载")
            return
        
        # 启动下载
        self.download_manager.start_download(task_id, task_info['uid'], save_path, self.log_download)
        
    def pause_download(self):
        """暂停下载选中任务"""
        task_id = self.get_selected_task_id()
        if task_id is None:
            return
        
        self.download_manager.pause_download(task_id)
        self.log_download(f"任务 {task_id} 已暂停")
        
    def delete_task(self):
        """删除选中的任务"""
        task_id = self.get_selected_task_id()
        if task_id is None:
            return
        
        # 获取任务信息
        task_info = self.db.get_task(task_id)
        if not task_info:
            self.log_download(f"找不到任务 {task_id}")
            return
        
        # 弹出确认对话框
        confirm = messagebox.askyesno(
            "确认删除",
            f"确定要删除任务 '{task_info['name']}'吗?\n\n这将删除数据库记录和所有相关文件!"
        )
        
        if not confirm:
            return
        
        # 停止下载任务
        if task_id in self.download_manager.active_tasks:
            self.download_manager.pause_download(task_id)
        
        # 删除文件
        try:
            self.delete_task_files(task_info)
            self.log_download(f"任务文件已删除: {task_info['name']}")
        except Exception as e:
            self.log_download(f"删除文件失败: {str(e)}")
        
        # 删除数据库记录
        try:
            self.db.delete_task(task_info['uid'])
            self.log_download(f"任务已删除: {task_info['name']}")
        except Exception as e:
            self.log_download(f"删除数据库记录失败: {str(e)}")
        
        # 刷新任务列表
        self.load_tasks()
    
    def delete_task_files(self, task_info):
        """删除任务相关的所有文件"""
        # 获取保存目录
        save_path = self.path_entry.get()
        task_dir = os.path.join(save_path, task_info['name'])
        
        # 删除临时TS文件
        for root, _, files in os.walk(task_dir):
            for file in files:
                if file.endswith('.ts') and file.startswith(task_info['uid']):
                    os.remove(os.path.join(root, file))
        
        # 删除合并的MP4文件
        mp4_file = os.path.join(task_dir, f"{task_info['name']}.mp4")
        if os.path.exists(mp4_file):
            os.remove(mp4_file)
        
        # 尝试删除空目录
        try:
            if os.path.exists(task_dir):
                os.rmdir(task_dir)
        except OSError:
            # 目录非空，保留目录
            pass

def main():
    root = Tk()
    app = M3U8DownloaderApp(root)
    root.mainloop()
    
# 主程序入口
if __name__ == "__main__":
    main()